package main

import (
	"github.com/hajimehoshi/ebiten/v2"
	"github.com/hajimehoshi/ebiten/v2/ebitenutil"
	"image"
	"image/color"
	"log"
)

type Game struct {
	input    *Input
	player   *Player
	cfg      *Config
	sceneMap *SceneMap
}

var frameCount int

func (g *Game) Update() error {
	g.input.Update(g.player)

	// 保存玩家当前位置
	oldX := g.player.x
	oldY := g.player.y

	// 根据玩家的移动方向设置playerMoving属性
	g.player.playerMoving = g.player.playerUp || g.player.playerDown || g.player.playerLeft || g.player.playerRight

	if g.player.playerMoving {
		// 预测玩家新位置
		newX, newY := oldX, oldY
		if g.player.playerUp {
			newY -= g.player.speed
		}
		if g.player.playerDown {
			newY += g.player.speed
		}
		if g.player.playerLeft {
			newX -= g.player.speed
		}
		if g.player.playerRight {
			newX += g.player.speed
		}

		// 检查新位置是否可移动
		if g.player.CanMoveTo(newX, newY, g.sceneMap) {
			// 更新玩家位置
			g.player.x = newX
			g.player.y = newY
		} else {
			// 不可移动时恢复旧位置
			g.player.x = oldX
			g.player.y = oldY
		}
		// 更新动画帧
		if frameCount%8 == 1 {
			g.player.playerFrame++
		}
	} else if frameCount%40 == 1 {
		g.player.playerFrame++
	}

	if ebiten.IsKeyPressed(ebiten.KeySpace) && !g.player.isPlanting {
		g.player.isPlanting = g.player.canPlanting(g.sceneMap)
		// 问题：当播放闲置动画时，如何在第二帧按下空格，浇水动画只会播放一帧 因为闲置动画给g.player.playerFrame设置为了1
		// 特殊判断，当帧数为1时手动赋值为0，无论何时按下都从浇水动画的第一帧开始播放
		if g.player.playerFrame == 1 {
			g.player.playerFrame = 0
		}
	}

	frameCount++
	if g.player.playerFrame > 3 {
		g.player.playerFrame = 0
	}

	if !g.player.playerMoving && !g.player.isPlanting && g.player.playerFrame > 1 {
		g.player.playerFrame = 0
	}

	if g.player.isPlanting && g.player.playerFrame > 1 {
		g.player.playerFrame = 0
		g.player.isPlanting = false
	}

	for _, tileStates := range g.player.mapIsPlanting {
		// 如果已经种植，开启计时器
		if tileStates.isPlanted && !tileStates.isMature {
			tileStates.timer++
			// 每秒更新60帧，60s后转换位成熟状态
			if tileStates.timer >= 10*60 {
				tileStates.isMature = true
			}
		}
	}

	return nil
}

func (g *Game) Draw(screen *ebiten.Image) {
	screen.Fill(color.RGBA{R: 148, G: 211, B: 197, A: 255})
	op := &ebiten.DrawImageOptions{}
	op.GeoM.Translate(8, 15)
	screen.DrawImage(g.sceneMap.mapFinish, op)
	for i, tileStates := range g.player.mapIsPlanting {
		flowerAllImage, _, err := ebitenutil.NewImageFromFile("../Image/Objects/BasicGrassBiomthings1.png")
		x := i % g.sceneMap.mapW
		y := i / g.sceneMap.mapW
		if err != nil {
			log.Fatal(err)
		}
		var flowerImage *ebiten.Image
		if tileStates.isPlanted {
			if tileStates.isMature {
				flowerImage = flowerAllImage.SubImage(image.Rect(16*7, 16*2, 16*8, 16*3)).(*ebiten.Image)
			} else {
				flowerImage = flowerAllImage.SubImage(image.Rect(16*6, 16*2, 16*7, 16*3)).(*ebiten.Image)
			}
			op := &ebiten.DrawImageOptions{}
			op.GeoM.Translate((float64)(x*16)+8.5, (float64)(y*16)+14.5)
			screen.DrawImage(flowerImage, op)
		}
	}
	g.player.Draw(screen, g.cfg)
}

func (g *Game) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeight int) {
	return 400, 350
}

func NewGame() *Game {
	cfg := loadConfig()
	ebiten.SetWindowSize(cfg.ScreenWidth, cfg.ScreenHeight)
	ebiten.SetWindowTitle(cfg.Title)
	icon, _, err := ebitenutil.NewImageFromFile("../image/icon.png")
	if err != nil {
		log.Fatal(err)
	}
	ebiten.SetWindowIcon([]image.Image{icon})

	sceneMap := newMap("Land1")
	player := NewPlayer(sceneMap)
	return &Game{
		input:    &Input{},
		sceneMap: sceneMap,
		player:   player,
		cfg:      cfg,
	}
}
